home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 January / macformat-020.iso / Shareware City / Developers / mega src / Source / ls.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-17  |  11.4 KB  |  519 lines  |  [TEXT/KAHL]

  1. /* ========================================
  2.  
  3.     ls.c
  4.     
  5.     Copyright (c) 1993,1994 Newport Software Development
  6.     
  7.     You may distribute unmodified copies of this file for
  8.     noncommercial purposes.  You may use this file as a
  9.     reference when writing your own nShell(tm) commands.
  10.     
  11.     All other rights are reserved.
  12.     
  13.    ======================================== */
  14.  
  15. #include <Packages.h>
  16.  
  17. #define LS_BUF_SIZ    4000
  18.    
  19. #include "nshc.h"
  20.                     
  21. #include "arg_utl.proto.h"
  22. #include "str_utl.proto.h"
  23. #include "nshc_utl.proto.h"
  24.  
  25. /* ======================================== */
  26.  
  27. void format_size( long size, char *p );
  28.  
  29. void format_size( long size, char *p )
  30. {
  31.     char    units;
  32.     
  33.     units = ' ';
  34.     
  35.     if (size > 9999) {
  36.         size /= 1024;
  37.         units = 'k';
  38.         }
  39.     
  40.     if (size > 9999) {
  41.         size /= 1024;
  42.         units = 'M';
  43.         }
  44.     
  45.     cStrFromNum( p, 4, size );
  46.     
  47.     p += 4;
  48.         
  49.     *p++ = units;
  50. }
  51.  
  52. /* ======================================== */
  53.  
  54. short ls_volume( Str255 path );
  55.  
  56. short ls_volume( Str255 path )
  57. {
  58.     Str255            localPath;
  59.     HParamBlockRec    pb;
  60.  
  61.     pb.volumeParam.ioCompletion = 0;
  62.     pb.volumeParam.ioNamePtr = localPath;
  63.     pb.volumeParam.ioVRefNum = 0;
  64.     pb.volumeParam.ioVolIndex = -1;
  65.     pStrCopy( localPath, path );
  66.         
  67.     if (!PBHGetVInfo(&pb, FALSE))
  68.         return( pb.volumeParam.ioVRefNum );
  69.     else
  70.         return(0);
  71. }
  72.  
  73. /* ======================================== */
  74.  
  75. void long_header( t_nshc_calls *nshc_calls, int option_time );
  76.  
  77. void long_header( t_nshc_calls *nshc_calls, int option_time )
  78. {
  79.     switch( option_time ) {
  80.         case 'g' :
  81.             nshc_calls->NSH_putStr("\p\r Crea Type RSize DSize  Creation Date       Name");
  82.             break;
  83.         case 'b' :
  84.             nshc_calls->NSH_putStr("\p\r Crea Type RSize DSize  Backup Date         Name");
  85.             break;
  86.         default :
  87.             nshc_calls->NSH_putStr("\p\r Crea Type RSize DSize  Modification Date   Name");
  88.             break;
  89.         }
  90.     nshc_calls->NSH_putStr("\p\r ---- ---- ----- ----- -------------------- ----\r");
  91. }
  92.  
  93. /* ======================================== */
  94.  
  95. int show_long( t_nshc_calls *nshc_calls, HFileInfo *fpb, Str255 path, int option_time );
  96.  
  97. int show_long( t_nshc_calls *nshc_calls, HFileInfo *fpb, Str255 path, int option_time )
  98. {
  99.     int            i;
  100.     int            index;
  101.     OSType        type;
  102.     char        *p;
  103.     char        line[LS_BUF_SIZ];
  104.     long        value;
  105.     Str255        string;
  106.     
  107.     index = 0;
  108.     line[index++] = ' ';
  109.  
  110.     if (fpb->ioFlAttrib & 16) {
  111.  
  112.         for (i=1; i<23; i++) line[index++] = ' ';
  113.                 
  114.         switch( option_time ) {
  115.             case 'g' :
  116.                 value = ((DirInfo *)fpb)->ioDrCrDat;
  117.                 break;
  118.             case 'b' :
  119.                 value = ((DirInfo *)fpb)->ioDrBkDat;
  120.                 break;
  121.             default :
  122.                 value = ((DirInfo *)fpb)->ioDrMdDat;
  123.                 break;
  124.             }                
  125.     
  126.         IUDateString( value, shortDate, string );
  127.         for (i=1; i<=(8 - string[0]); i++) line[index++] = ' ';
  128.         for (i=1; i<=string[0]; i++) line[index++] = string[i];
  129.         line[index++] = ' ';
  130.         
  131.         IUTimeString( value, 1, string );
  132.         for (i=1; i<=(11 - string[0]); i++) line[index++] = ' ';
  133.         for (i=1; i<=string[0]; i++) line[index++] = string[i];
  134.         line[index++] = ' ';
  135.         
  136.         }
  137.     else {
  138.             
  139.         type = fpb->ioFlFndrInfo.fdCreator;        
  140.         p = (char *) &type;
  141.         for ( i=0; i<4; i++ ) line[index++] = *p++;
  142.         line[index++] = ' ';
  143.     
  144.         type = fpb->ioFlFndrInfo.fdType;        
  145.         p = (char *) &type;
  146.         for ( i=0; i<4; i++ ) line[index++] = *p++;
  147.         line[index++] = ' ';
  148.         
  149.         format_size( (fpb->ioFlRLgLen), &line[index] );
  150.         index += 5;
  151.         line[index++] = ' ';
  152.         
  153.         format_size( (fpb->ioFlLgLen), &line[index] );
  154.         index += 5;
  155.         line[index++] = ' ';
  156.         
  157.         switch( option_time ) {
  158.             case 'g' :
  159.                 value = fpb->ioFlCrDat;
  160.                 break;
  161.             case 'b' :
  162.                 value = fpb->ioFlBkDat;
  163.                 break;
  164.             default :
  165.                 value = fpb->ioFlMdDat;
  166.                 break;
  167.             }
  168.                 
  169.         IUDateString( value, shortDate, string );
  170.         for (i=1; i<=(8 - string[0]); i++) line[index++] = ' ';
  171.         for (i=1; i<=string[0]; i++) line[index++] = string[i];
  172.         line[index++] = ' ';
  173.         
  174.         IUTimeString( value, 1, string );
  175.         for (i=1; i<=(11 - string[0]); i++) line[index++] = ' ';
  176.         for (i=1; i<=string[0]; i++) line[index++] = string[i];
  177.         line[index++] = ' ';
  178.         }
  179.         
  180.     for ( i=1; i<=path[0]; i++ )
  181.         line[index++] = path[i];
  182.             
  183.     line[index++] = '\r';
  184.     line[index] = 0;
  185.         
  186.     nshc_calls->NSH_puts(line);
  187. }
  188.  
  189. /* ======================================== */
  190.  
  191. int do_long( t_nshc_calls *nshc_calls, short volume, Str255 path, int option_time, int is_list, int first_call );
  192.  
  193. int do_long( t_nshc_calls *nshc_calls, short volume, Str255 path, int option_time, int is_list, int first_call )
  194. {
  195.     CInfoPBRec    cipbr;
  196.     HFileInfo    *fpb;
  197.     short        idx;
  198.     short        foundDir;
  199.     Str255        localPath;
  200.     
  201.     fpb = (HFileInfo *)&cipbr;
  202.     
  203.     fpb->ioVRefNum = volume;
  204.     fpb->ioDirID = 0;
  205.     fpb->ioFDirIndex = 0;
  206.     fpb->ioNamePtr = localPath;
  207.     pStrCopy( localPath, path );
  208.  
  209.     if (PBGetCatInfo( &cipbr, FALSE )) {
  210.         nshc_calls->NSH_putStr_err("\pls: ioDirID not found.\r");
  211.         return(1);
  212.         }
  213.         
  214.     foundDir = fpb->ioDirID;
  215.  
  216.     if (fpb->ioFlAttrib & 16) {
  217.         if (is_list) {
  218.             nshc_calls->NSH_putStr("\p\rDir = ");
  219.             nshc_calls->NSH_putStr(path);
  220.             nshc_calls->NSH_putStr("\p\r\r");
  221.             }
  222.         if (is_list || first_call) {
  223.             long_header( nshc_calls, option_time );
  224.             }
  225.         for( idx=1; TRUE; idx++) {                        /* indexing loop */
  226.             fpb->ioVRefNum = volume;
  227.             fpb->ioDirID = foundDir;                    /* must set on each loop */
  228.             fpb->ioFDirIndex = idx;
  229.             pStrCopy( localPath, path );
  230.         
  231.             if (PBGetCatInfo( &cipbr, FALSE )) break;    /* exit when no more entries */
  232.  
  233.             show_long( nshc_calls, fpb, localPath, option_time );
  234.             }
  235.         nshc_calls->NSH_putchar('\r');
  236.         }
  237.     else
  238.         show_long( nshc_calls, fpb, localPath, option_time );
  239.  
  240.     return(0);
  241. }
  242.  
  243.  /* ======================================== */
  244.  
  245. int do_cols( t_nshc_calls *nshc_calls, short volume, Str255 path, int cols, int is_list );
  246.  
  247. int do_cols( t_nshc_calls *nshc_calls, short volume, Str255 path, int cols, int is_list )
  248. {
  249.     CInfoPBRec    cipbr;
  250.     HFileInfo    *fpb;
  251.     short        idx, foundDir;
  252.     Str255        localPath;
  253.     int            blanks;
  254.     int            count;
  255.     int            column_width;
  256.     int            i, cmax;
  257.     int            buf_ptr;
  258.     char        buf[LS_BUF_SIZ];
  259.  
  260.     fpb = (HFileInfo *)&cipbr;
  261.     
  262.     fpb->ioVRefNum = volume;
  263.     fpb->ioDirID = 0;
  264.     fpb->ioFDirIndex = 0;
  265.     fpb->ioNamePtr = localPath;
  266.     pStrCopy( localPath, path );
  267.  
  268.     if (PBGetCatInfo( &cipbr, FALSE )) {
  269.         nshc_calls->NSH_putStr_err("\pls: ioDirID not found.\r");
  270.         return(1);
  271.         }
  272.         
  273.     if (fpb->ioFlAttrib & 16) {
  274.     
  275.         if (is_list) {
  276.             nshc_calls->NSH_putStr("\p\rDir = ");
  277.             nshc_calls->NSH_putStr(path);
  278.             nshc_calls->NSH_putStr("\p\r\r");
  279.             }
  280.  
  281.         foundDir = fpb->ioDirID;
  282.         count = 0;
  283.  
  284.         column_width = 0;
  285.  
  286.         for( idx=1; TRUE; idx++) {
  287.             fpb->ioVRefNum = volume;
  288.             fpb->ioDirID = foundDir;
  289.             fpb->ioFDirIndex = idx;
  290.             pStrCopy( localPath, path );
  291.             if (PBGetCatInfo( &cipbr, FALSE ))        // returns non-zero when no more
  292.                 break;
  293.             i = localPath[0] + 5;
  294.             if (i > column_width) column_width = i;
  295.             }
  296.         
  297.         buf_ptr = 0;
  298.         
  299.         for( idx=1; TRUE; idx++) {
  300.             fpb->ioVRefNum = volume;
  301.             fpb->ioDirID = foundDir;
  302.             fpb->ioFDirIndex = idx;
  303.             pStrCopy( localPath, path );
  304.         
  305.             if (PBGetCatInfo( &cipbr, FALSE ))        // returns non-zero when no more
  306.                 break;
  307.         
  308.             count++;
  309.         
  310.             cmax = localPath[0];
  311.             
  312.             if ( (buf_ptr + column_width + 2 ) > LS_BUF_SIZ ) {
  313.                 buf[buf_ptr] = 0;
  314.                 nshc_calls->NSH_puts(buf);
  315.                 buf_ptr = 0;
  316.                 }
  317.  
  318.             for ( i = 1 ; i <= cmax ; i ++ )
  319.                 buf[buf_ptr++] = localPath[i];
  320.     
  321.             blanks = column_width - cmax;
  322.  
  323.             if (fpb->ioFlAttrib & 16) {
  324.                 buf[buf_ptr++] = ':';
  325.                 blanks--;
  326.                 }
  327.  
  328.             if (count % cols) {
  329.                 while (blanks--)
  330.                     buf[buf_ptr++] = ' ';
  331.                 }
  332.             else {
  333.                 buf[buf_ptr++] = '\r';
  334.                 count = 0;
  335.                 }
  336.             }
  337.     
  338.         if (buf_ptr) {
  339.             buf[buf_ptr++] = '\r';
  340.             buf[buf_ptr] = 0;
  341.             nshc_calls->NSH_puts(buf);
  342.             }
  343.         nshc_calls->NSH_putchar('\r');
  344.         }
  345.     else {
  346.         nshc_calls->NSH_putStr(localPath);
  347.         nshc_calls->NSH_putchar('\r');
  348.         }
  349.  
  350.     
  351.     return(0);
  352. }
  353.  
  354.  /* ======================================== */
  355.  
  356. int do_fast( t_nshc_calls *nshc_calls, short volume, Str255 path, int is_list );
  357.  
  358. int do_fast( t_nshc_calls *nshc_calls, short volume, Str255 path, int is_list )
  359. {
  360.     CInfoPBRec        cipbr;
  361.     HFileInfo        *fpb;
  362.     short            idx, foundDir;
  363.     Str255            localPath;
  364.     int                ci, cmax;
  365.     int                buf_ptr;
  366.     char            buf[LS_BUF_SIZ];
  367.     
  368.     fpb = (HFileInfo *)&cipbr;
  369.     
  370.     fpb->ioVRefNum = volume;
  371.     fpb->ioDirID = 0;
  372.     fpb->ioFDirIndex = 0;
  373.     fpb->ioNamePtr = localPath;
  374.     pStrCopy( localPath, path );
  375.  
  376.     if (PBGetCatInfo( &cipbr, FALSE )) {
  377.         nshc_calls->NSH_putStr_err("\pls: File or directory not found.\r");
  378.         return(1);
  379.         }
  380.         
  381.     if (fpb->ioFlAttrib & 16) {
  382.  
  383.         if (is_list) {
  384.             nshc_calls->NSH_putStr("\p\rDir = ");
  385.             nshc_calls->NSH_putStr(path);
  386.             nshc_calls->NSH_putStr("\p\r\r");
  387.             }
  388.  
  389.         foundDir = fpb->ioDirID;
  390.         buf_ptr = 0;
  391.  
  392.         for( idx=1; TRUE; idx++) {                        /* indexing loop */
  393.             fpb->ioVRefNum = volume;
  394.             fpb->ioDirID = foundDir;                    /* must set on each loop */
  395.             fpb->ioFDirIndex = idx;
  396.             pStrCopy( localPath, path );
  397.         
  398.             if (PBGetCatInfo( &cipbr, FALSE )) break;    /* exit when no more entries */
  399.             
  400.             cmax = localPath[0];
  401.             
  402.             if ( (buf_ptr + cmax + 3 ) > LS_BUF_SIZ ) {
  403.                 buf[buf_ptr] = 0;
  404.                 nshc_calls->NSH_puts(buf);
  405.                 buf_ptr = 0;
  406.                 }
  407.             else {
  408.                 for ( ci = 1 ; ci <= cmax ; ci ++ )
  409.                     buf[buf_ptr++] = localPath[ci];
  410.  
  411.                 if (fpb->ioFlAttrib & 16)
  412.                     buf[buf_ptr++] = ':';
  413.         
  414.                 buf[buf_ptr++] = '\r';
  415.                 }
  416.             }
  417.             
  418.             if (buf_ptr) {
  419.                 buf[buf_ptr] = 0;
  420.                 nshc_calls->NSH_puts(buf);
  421.                 }
  422.         nshc_calls->NSH_putchar('\r');
  423.         }
  424.     else {
  425.         nshc_calls->NSH_putStr(localPath);
  426.         nshc_calls->NSH_putchar('\r');
  427.         }
  428.     
  429.     return(0);
  430. }
  431.  
  432.   /* ======================================== */ 
  433.  
  434. void main(t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls)
  435. {
  436.     int        option_cols;
  437.     int        option_long;
  438.     int        option_time;
  439.     int        cArg;
  440.     int        arg;
  441.     int        argc;
  442.     int        cols;
  443.     Str255    path;
  444.     int        path_ok;
  445.     int        error;
  446.     int        count;
  447.     int        first_call;
  448.     short    volume;
  449.         
  450.     error = nshc_bad_version( nshc_parms, nshc_calls, NSHC_VERSION );
  451.     
  452.     if (!error) {
  453.         option_long = nshc_got_option( nshc_parms, 'l' );
  454.         option_cols = nshc_got_option( nshc_parms, 'c' );
  455.         option_time = 'm'; // modification
  456.         if (nshc_got_option( nshc_parms, 'b' )) option_time = 'b';
  457.         if (nshc_got_option( nshc_parms, 'g' )) option_time = 'g';
  458.         if (cArg = nshc_got_option( nshc_parms, 'c' ))
  459.             if ( nshc_is_numeric_operand( nshc_parms, ++cArg ) )
  460.                 cols = arg_to_int( nshc_parms, cArg );
  461.             else {
  462.                 nshc_calls->NSH_putStr_err("\pUsage: ls [<path1> <path2>...] [-c columns] [-l [-m] [-b] [-g]].\r");
  463.                 error = NSHC_ERR_PARMS;
  464.                 }
  465.         }
  466.     
  467.     count = 0;
  468.     
  469.     first_call = 1;
  470.     
  471.     argc = nshc_parms->argc;
  472.     
  473.     for (arg = 1; arg < argc; arg++ )
  474.         if (!error)
  475.             if (arg != cArg)
  476.                 if (nshc_is_operand(nshc_parms, arg)) {
  477.                     count++;
  478.                     pStrFromC( path, &(nshc_parms->arg_buf[nshc_parms->argv[arg]]) );
  479.                     error = nshc_calls->NSH_path_expand(path);
  480.                     if (!error)
  481.                         volume = ls_volume( path );
  482.                     if (!error && volume) {
  483.                         if (option_long)
  484.                             error = do_long(nshc_calls, volume, path, option_time, 1, first_call);
  485.                         else
  486.                             if ((option_cols) && (cols > 1))
  487.                                 error = do_cols(nshc_calls, volume, path, cols, 1);
  488.                             else
  489.                                 error = do_fast(nshc_calls, volume, path, 1);
  490.                         }
  491.                     else
  492.                         nshc_calls->NSH_putStr_err("\pls: File or directory not found.\r");
  493.                     first_call = 0;
  494.                     }
  495.         
  496.     if (!(error || count))
  497.         if (nshc_calls->NSH_var_env( "\pPWD", path )) {
  498.             nshc_calls->NSH_putStr_err("\pls: PWD not found.\r");
  499.             error = 1;
  500.             }
  501.         else
  502.             if ( volume = ls_volume( path ) ) {
  503.                 if (option_long)
  504.                     error = do_long(nshc_calls, volume, path, option_time, 0, 1);
  505.                 else
  506.                     if (option_cols)
  507.                         error = do_cols(nshc_calls, volume, path, cols, 0);
  508.                     else
  509.                         error = do_fast(nshc_calls, volume, path, 0);
  510.                 }
  511.             else {
  512.                 nshc_calls->NSH_putStr_err("\pls: PWD volume not found.\r");
  513.                 error = 1;
  514.                 }
  515.  
  516.     nshc_parms->action = nsh_idle;
  517.     nshc_parms->result = error;
  518. }
  519.